package feeinterface.protocol.req;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import org.apache.log4j.Logger;

import com.ulwx.tool.ObjectUtils;
import com.ulwx.tool.RequestUtils;
import com.ulwx.tool.StringUtils;


import feeinterface.protocol.res.ErrorBean;

import feeinterface.protocol.res.ModelMayBigSize;
import feeinterface.protocol.utils.Constants;
import feeinterface.protocol.utils.Translate;

/**
 * 交换操作类
 * 
 * @author 黄杰
 * 
 */
public class Exchange {

	private static Logger log = Logger.getLogger(Exchange.class);

	/**
	 * 根据协议编号获取协议类
	 * 
	 * @param Protocol
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("all")
	public static Protocol geProtocol(String Protocol) throws Exception {
		try {
			if (StringUtils.hasText(Protocol)) {
				String className = Constants.PROTOCOL_REQ_CLASSPATH + Protocol;
				Class cls = Class.forName(className);
				return (Protocol) cls.newInstance();
			}
		} catch (Exception e) {
			log.error("获取对象出错！", e);
			throw e;
		}
		return null;
	}

	/**
	 * 注入请求参数
	 * 
	 * @param pro
	 * @param ru
	 * @param bodyBytes
	 * @throws Exception
	 */
	@SuppressWarnings("all")
	public static void injectRequestParmater(Protocol pro, RequestUtils ru,
			byte[] bodyBytes) throws Exception {

		Class c = pro.getClass();
		
		Field[] fields = c.getDeclaredFields();
		if (fields != null) {
			for (int i = 0; i < fields.length; i++) {

				Field field = fields[i];
				field.setAccessible(true);

				int mod = field.getModifiers();
				if (mod == Modifier.PUBLIC) {
					String fileName = field.getName();
					if (fileName.equals("BodyBytes")) {
						field.set(pro, bodyBytes);
						continue;
					}
					Class filedClass = field.getType();
					if (filedClass == Integer.class || filedClass == int.class) {
						Integer value = ru.getInt(fileName);
						if(value==null) value=0;
						field.set(pro, value);
					} else if (filedClass == Byte.class
							|| filedClass == byte.class) {
						Integer value = ru.getInt(fileName);
						field.set(pro, value);
					} else if (filedClass == Short.class
							|| filedClass == short.class) {
						Integer value = ru.getInt(fileName);
						field.set(pro, value);
					} else {
						String value = ru.getString(fileName);
						field.set(pro, value);
					}

				}
			}
		}
		// 注入RequestUtils
		pro.setRequest(ru);

	}

	public static byte[] gen(RequestUtils ru) {
		return Exchange.gen(ru, new byte[0]);
	}

	public static byte[] gen(RequestUtils ru, byte[] BodyBytes) {

		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(bout);
		Boolean debug = ru.getBoolean("Debug");
		boolean flag = false;
		Object javaBean = null;
		String protocolId = "";
		try {

			protocolId = ru.getString("Protocol");
			if (StringUtils.hasText(protocolId)) {

				// 得到协议处理类的Class对象
				Protocol pro = Exchange.geProtocol(protocolId);

				if (pro == null) {
					throw new Exception("无法根据配置找到需处理的协议操作类！");
				}
//				if (pro instanceof ProDownload) {
//					isDownLoad = true;
//				}
				// 对协议处理类注入请求参数
				Exchange.injectRequestParmater(pro, ru, BodyBytes);

				String val = pro.validate();

				if (val == null) {
					// 前置验证成功，调用业务类逻辑处理方法genBean()得到输出对象，

					javaBean = pro.genBean();

					flag = true;// 要进行后置验证

				} else {
					log.error("验证失败!" + val);

					javaBean = ErrorBean.getErrorBean(protocolId, val);
					;
					// Exchange.output(debug, dout, et);
				}

			} else {
				log.error("客户端协议号为空！");

				javaBean = ErrorBean.getErrorBean(protocolId, "客户端协议号为空！");

			}

		} catch (ExchangeException ex) {
			log.error("", ex);
			// ErrorType et = new ErrorType();
			// getErrorStream(et, ex.getStatus(), ex.getMessage(), dout);

			javaBean = ErrorBean.getErrorBean(protocolId, ex.getMessage());

		} catch (Throwable ex) {
			log.error("", ex);

			javaBean = ErrorBean.getErrorBean(protocolId, "网络繁忙，请稍候再试。");

		}

		try {
			if (javaBean==null) {
				dout.writeByte(0);
			} else {
				Exchange.output(debug, dout, javaBean);
			}
		} catch (Exception e) {
			log.error("", e);
		} finally {
			try {
				dout.close();
			} catch (IOException e) {
				log.error("error close..." + e.getMessage());
			}
		}

		byte[] res = bout.toByteArray();
		if (flag && (res.length > 1024 * 100)) {// 如果需要进行后置验证，并且处理的包大于100k,要进行缩减协议包处理
			// 如果返回的长度大于100k，
			log.info("协议包超过100k，进行缩小协议包处理！");
			if (javaBean instanceof ModelMayBigSize) {
				log.info("进行处理....");
				ModelMayBigSize mmb = (ModelMayBigSize) javaBean;
				javaBean = mmb.getModelWhenBigSize();
				// 重新生成协议包
				try {
					Exchange.output(debug, dout, javaBean);
				} catch (Exception e) {
					log.error("", e);
				}

			}

		}
		
		if (log.isDebugEnabled()) {
			try {
				String returnResult=ObjectUtils.toString(ObjectUtils
						.CloneWithDeep(javaBean,
								byte[].class));
				log.debug("return Result:"
						+returnResult );
				returnResult=StringUtils.trim(returnResult);

				ru.setString(Constants.LogKey.RETURN_RESULT, returnResult);
			} catch (Exception e) {
				log.error("", e);
			}
		}
		return res;

	}

	public static void output(Boolean debug, DataOutputStream dout, Object obj)
			throws Exception {

		if (debug != null && debug) {
			String debugStr = ObjectUtils.toString(ObjectUtils
					.CloneWithDeep(obj));
			try {
				byte[] res = debugStr.getBytes("utf-8");
				dout.write(res);
			} catch (Exception ee) {
				log.error("", ee);
			}
		} else {

			Translate.translateObjectToStream(obj, dout);

		}

	}
}
